package initialize

import (
	"encoding/hex"
	"github.com/FISCO-BCOS/go-sdk/client"
	"github.com/FISCO-BCOS/go-sdk/conf"
	"github.com/FISCO-BCOS/go-sdk/smcrypto"
	"github.com/ethereum/go-ethereum/common"
	"github.com/pkg/errors"
	"go.uber.org/zap"
	"log"
	"path"
	"portal_rpc/contracts/portal"
	"portal_rpc/global"
)

// InitPortalManager 初始化 portal manager
func InitPortalManager(mode string) {

	var (
		err                 error
		portalProverAddress common.Address
	)

	// 初始化 client
	global.Client, portalProverAddress, err = initClientAndPortalProverAddress(mode)
	if err != nil {
		zap.L().Error("init client and portal prover address failed", zap.Error(err))
		return
	}

	// 初始化 account address
	global.Deployer, global.PortalProver, global.TradeProver, global.TradeAuditor, err = initAddresses()
	if err != nil {
		zap.L().Error("init address failed", zap.Error(err))
		return
	}
	if global.PortalProver.Hex() != portalProverAddress.Hex() {
		zap.L().Error("portal prover config are not the same(config.toml,config.yaml)")
		return
	}
	zap.L().Debug(global.Deployer.Hex())
	zap.L().Debug(portalProverAddress.Hex())
	zap.L().Debug(global.PortalProver.Hex())
	zap.L().Debug(global.TradeProver.Hex())
	zap.L().Debug(global.TradeAuditor.Hex())

	// load portal manager
	portalAddress := common.HexToAddress(global.ServerConfig.Chain.PortalManager)
	global.PortalManager, err = portal.NewPortal(portalAddress, global.Client)
	if err != nil {
		zap.L().Error("create portal instance failed", zap.Error(err))
		return
	}

	/*
		// 2. load trust manager
		trustAddress := common.HexToAddress(global.ServiceConfig.TrustManager)
		trustManager, err := trust.NewTrust(trustAddress, cli)
		if err != nil {
			zap.L().Error("create trust instance failed", zap.Error(err))
			return
		}

		// 3. load trade manager
		tradeAddress := common.HexToAddress(global.ServiceConfig.TradeManager)
		tradeManager, err := trade.NewTrade(tradeAddress, cli)
		if err != nil {
			zap.L().Error("create trade instance failed", zap.Error(err))
			return
		}
	*/
}

// initClientAndPortalProverAddress 初始化client以及对应的deployer的地址
func initClientAndPortalProverAddress(mode string) (cli *client.Client, portalProver common.Address, err error) {

	// 加载client配置文件信息
	configs, err := conf.ParseConfigFile(path.Join("etc", "chain", "chain-"+mode+".toml"))
	if err != nil {
		return nil, common.Address{}, errors.Wrap(err, "parse config.toml failed")
	}
	config := &configs[0]

	// 国密获取帐号地址的方式
	portalProverAddress := smcrypto.SM2KeyToAddress(config.PrivateKey)

	zap.L().Debug("portal prover address", zap.String("prover address", portalProverAddress.Hex()))

	cli, err = client.Dial(config)
	if err != nil {
		log.Fatal(err)
	}
	zap.L().Debug("portal prover private key", zap.String("private key", hex.EncodeToString(config.PrivateKey)))
	return cli, portalProverAddress, nil
}

// initAddresses 初始化地址
func initAddresses() (deployer common.Address, portalProver common.Address, tradeProver common.Address, tradeAuditor common.Address, err error) {
	// deployer
	deployerKey, _, err := conf.LoadECPrivateKeyFromPEM("./account/" + global.ServerConfig.Chain.Deployer + ".pem")
	if err != nil {
		return common.Address{}, common.Address{}, common.Address{}, common.Address{}, errors.Wrap(err, "load deployer failed")
	}
	deployer = smcrypto.SM2KeyToAddress(deployerKey)

	// portal prover
	portalProverKey, _, err := conf.LoadECPrivateKeyFromPEM("./account/" + global.ServerConfig.Chain.PortalProver + ".pem")
	if err != nil {
		return common.Address{}, common.Address{}, common.Address{}, common.Address{}, errors.Wrap(err, "load portal prover failed")
	}
	portalProver = smcrypto.SM2KeyToAddress(portalProverKey)

	// trade prover
	tradeProverKey, _, err := conf.LoadECPrivateKeyFromPEM("./account/" + global.ServerConfig.Chain.TradeProver + ".pem")
	if err != nil {
		return common.Address{}, common.Address{}, common.Address{}, common.Address{}, errors.Wrap(err, "load trade prover failed")
	}
	tradeProver = smcrypto.SM2KeyToAddress(tradeProverKey)

	// trade auditor
	tradeAuditorKey, _, err := conf.LoadECPrivateKeyFromPEM("./account/" + global.ServerConfig.Chain.TradeAuditor + ".pem")
	if err != nil {
		return common.Address{}, common.Address{}, common.Address{}, common.Address{}, errors.Wrap(err, "load trade auditor failed")
	}
	tradeAuditor = smcrypto.SM2KeyToAddress(tradeAuditorKey)

	return deployer, portalProver, tradeProver, tradeAuditor, nil
}
